package com.sneakxy.mybase4j.generator.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * 注解
 * @author 潜行的青衣
 * @see
 */
public class Annotation implements Type {
	
	private String name;
	
	private String packageName;
	
	private Map<String, List<String>> arguments = new LinkedHashMap<String, List<String>>();

	private boolean hasPackage = false;
	
	/**
	 * @param type
	 */
	public Annotation(Class<?> type) {
		if(type == null) {
			throw new NullPointerException("type could not be null.");
		}
		this.name = type.getName();
		this.init();
	}

	public Annotation(String fullName) {
		this.name = StringUtils.trimToEmpty(fullName);
		if(StringUtils.isBlank(this.name)) {
			throw new NullPointerException("fullName could not be null.");
		}
		this.init();
	}
	
	private void init() {
		if(StringUtils.indexOf(this.name, ".") > -1) {
			int lastIndex = StringUtils.lastIndexOf(this.name, ".");
			this.packageName = StringUtils.substring(name, 0, lastIndex);
			if(StringUtils.equals(this.packageName, "java.lang")) {
				this.packageName = null;
			}
			this.name = StringUtils.substring(this.name, lastIndex + 1);
		}
	}
	
	public void addArgument(String name, String value) {
		List<String> values = this.arguments.get(name);
		if(values == null) {
			values = new ArrayList<String>();
			arguments.put(name, values);
		}
		values.add(value);
	}
	
	@Override
	public String toString(boolean isNotImport) {
		StringBuilder s = new StringBuilder();
		if(isNotImport) {
			s.append("@");
		}
		if(!isNotImport || (this.isHasPackage() && this.hasImportPackage())) {
			s.append(this.getImportPackage()).append(".");
		}
		s.append(this.getTypeName());
		if(isNotImport && !this.arguments.isEmpty()) {
			s.append("(");
			Iterator<Entry<String, List<String>>> it = this.arguments.entrySet().iterator();
			Entry<String, List<String>> argument = null;
			List<String> value = null;
			Iterator<String> vit = null;
			boolean multi = false;
			while(it.hasNext()) {
				argument = it.next();
				value = argument.getValue();
				multi = value.size() > 1; 
				s.append(argument.getKey()).append(StringUtils.isBlank(argument.getKey()) ? "" : " = ");
				if(multi) {
					s.append("{");
				}
				vit = value.iterator();
				while(vit.hasNext()) {
					s.append(vit.next());
					if(vit.hasNext()) {
						s.append(", ");
					}
				}
				if(multi) {
					s.append("}");
				}
				if(it.hasNext()) {
					s.append(", ");
				}
			}
			s.append(")");
		}
		return s.toString();
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybase4j.generator.core.Type#hasImportPackage()
	 */
	@Override
	public boolean hasImportPackage() {
		return StringUtils.isNotBlank(packageName);
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybase4j.generator.core.Type#isHasPackage()
	 */
	public boolean isHasPackage() {
		return hasPackage;
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybase4j.generator.core.Type#setHasPackage(boolean)
	 */
	@Override
	public void setHasPackage(boolean hasPackage) {
		this.hasPackage = hasPackage;
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybase4j.generator.core.Type#getTypeName()
	 */
	@Override
	public String getTypeName() {
		return this.name;
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybase4j.generator.core.Type#getImportPackage()
	 */
	@Override
	public String getImportPackage() {
		return this.packageName;
	}
	
	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(this.getTypeName()).toHashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj == this) {
			return true;
		}
		if(!(obj instanceof Type)) {
			return false;
		}
		Type type = (Type) obj ;
		return new EqualsBuilder().append(type.getTypeName(), this.getTypeName()).isEquals();
	}
}
